 
package com.zdkj.subway.rca.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.excel.EasyExcel;

import com.alibaba.excel.read.builder.ExcelReaderBuilder;
import com.alibaba.excel.read.metadata.ReadSheet;
import com.alibaba.excel.util.DateUtils;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import com.zdkj.common.core.exceltools.MultipartFileToFile;
import com.zdkj.common.security.util.ObjectUtils;
import com.zdkj.subway.rca.util.MyDateUtil;
import com.zdkj.subway.rca.entity.SwCkBankCashPaymentNote;
import com.zdkj.subway.rca.entity.SwCkBankCashPaymentNoteTmp;

import com.zdkj.subway.rca.enums.SW_CK_BANK_CASH_PAYMENT_NOTE_DATA_TYPE;
import com.zdkj.subway.rca.mapper.SwCkBankCashPaymentNoteTmpMapper;
import com.zdkj.subway.rca.service.SwCkBankCashPaymentNoteTmpService;
import com.zdkj.subway.rca.service.SwCkBankCashPaymentNoteService;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletResponse;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.text.ParseException;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.*;

/**
 * 银行现金缴款单临时表
 *
 * @author stw
 * @date 2020-12-10 10:55:09
 */
@Transactional(rollbackFor = Exception.class)
@Service
public class SwCkBankCashPaymentNoteTmpServiceImpl extends ServiceImpl<SwCkBankCashPaymentNoteTmpMapper, SwCkBankCashPaymentNoteTmp> implements SwCkBankCashPaymentNoteTmpService {
    private static final Logger LOGGER = LoggerFactory.getLogger(SwCkBankCashPaymentNoteTmpServiceImpl.class);
    private String parsePattern = "yyyy-MM-dd";
    @Autowired
    private SwCkBankCashPaymentNoteService swCkBankCashPaymentNoteService;

    @Override
    public Boolean saveBatchWithExcel(final File excelFile,String tradeDate) throws Exception {
        ExcelReaderBuilder excelReaderBuilder = EasyExcel.read(excelFile);

        List<ReadSheet> sheets = excelReaderBuilder.build().excelExecutor().sheetList();
        List<SwCkBankCashPaymentNoteTmp> listDb = new ArrayList<>();
        for(int n = 0; n < sheets.size(); n++) {
            String lineName = sheets.get(n).getSheetName();

            List<Map<Integer, String>> listMap = excelReaderBuilder.sheet(n).headRowNumber(2).doReadSync();
            List<Map<String,String>> lineMap = this.baseMapper.selectLineMap();
            List<Map<String,String>> stationMap = this.baseMapper.selectStationMap();

            if (CollectionUtil.isNotEmpty(listMap)) {
                Map<Integer, String> dataTradeTime = listMap.get(0);
                LOGGER.info("读取到日期行数据:{}", JSON.toJSONString(dataTradeTime));
               int tradeTimeIndex = 0;
               int index = 2;
                while(true) {
                    String tradeTimeOld = dataTradeTime.get(index);
                    String tradeTime = null;
                    if(tradeTimeOld!= null && Character.isDigit(tradeTimeOld.toCharArray()[0])){
                        tradeTime = formatExcelDate(Integer.parseInt(tradeTimeOld.substring(0,tradeTimeOld.indexOf("."))));
                    }

                    if (tradeDate.equals(tradeTime)) {
                        tradeTimeIndex = index;
                        break;
                    }
                    if("合计".equals(tradeTime) || index > 100){
                        break;
                    }
                    index ++;
                }

                for (int m = 1; m < listMap.size(); m++) {

                    Map<Integer, String> data = listMap.get(m);
                    // 返回每条数据的键值对 表示所在的列 和所在列的值
                    LOGGER.info("读取到数据:{}", JSON.toJSONString(data));
                    if(data.get(0) == null || !Character.isDigit(data.get(0).toCharArray()[0])){
                        continue;
                    }

                    SwCkBankCashPaymentNoteTmp tmpObj = new SwCkBankCashPaymentNoteTmp();
                    tmpObj.setLineCodeTmp(lineName);
                    tmpObj.setStationCodeTmp(data.get(1));//车站
                    tmpObj.setTradeTimeTmp(tradeDate);
                    tmpObj.setAmountTmp(data.get(tradeTimeIndex));

                    if (StringUtils.isEmpty(tmpObj.getTradeTimeTmp())
                            || StringUtils.isEmpty(tmpObj.getAmountTmp())
                            || StringUtils.isEmpty(tmpObj.getLineCodeTmp())
                            || StringUtils.isEmpty(tmpObj.getStationCodeTmp())
                            ) {
                        continue;
                    }
                    if (!parseDate(tmpObj.getTradeTimeTmp())) {
                        continue;
                    }

                    final SwCkBankCashPaymentNoteTmp obj = ObjectUtils.getDefaultObj(SwCkBankCashPaymentNoteTmp.class);
                    BeanUtils.copyProperties(tmpObj, obj,  "creatorId", "creatorName");
                    checkErr(obj,lineMap,stationMap);
                    listDb.add(obj);
                }
            }
        }


        MultipartFileToFile.delteTempFile(excelFile);
        if(!listDb.isEmpty()) {
            Map<String, Object> columnMap = new HashMap<>();
            columnMap.put("CREATOR_ID", listDb.get(0).getCreatorId());
            this.baseMapper.deleteByMap(columnMap);
            return  this.saveBatch(listDb);
        }

        return false;

    }

	@Override
    public Boolean saveBatchWithExcel(final File excelFile,String beginDate,String endDate) throws Exception {
        //计算两个日期之间都含有具体哪些日期
		List<String> listBetweenDates = MyDateUtil.getDatesBetweenTwoDate(beginDate, endDate);
	    if(listBetweenDates==null){
	    	return false;
	    }
        ExcelReaderBuilder excelReaderBuilder = EasyExcel.read(excelFile);

        List<ReadSheet> sheets = excelReaderBuilder.build().excelExecutor().sheetList();
        List<SwCkBankCashPaymentNoteTmp> listDb = new ArrayList<>();
        for(int n = 0; n < sheets.size(); n++) {
            String lineName = sheets.get(n).getSheetName();

            List<Map<Integer, String>> listMap = excelReaderBuilder.sheet(n).headRowNumber(2).doReadSync();
            List<Map<String,String>> lineMap = this.baseMapper.selectLineMap();
            List<Map<String,String>> stationMap = this.baseMapper.selectStationMap();
			LinkedHashMap<String,Integer> tradeTimeList = new LinkedHashMap<>();//日期和所在位置存放变量

            if (CollectionUtil.isNotEmpty(listMap)) {
                Map<Integer, String> dataTradeTime = listMap.get(0);
                LOGGER.info("读取到日期行数据:{}", JSON.toJSONString(dataTradeTime));              
               int index = 2;
                while(true) {
                    String tradeTimeOld = dataTradeTime.get(index);
                    String tradeTime = null;
                    if(tradeTimeOld!= null && Character.isDigit(tradeTimeOld.toCharArray()[0]) && tradeTimeOld.contains(".")){
                        tradeTime = formatExcelDate(Integer.parseInt(tradeTimeOld.substring(0,tradeTimeOld.indexOf("."))));
                    }
                    /*
                    if (tradeDate.equals(tradeTime)) {
                        tradeTimeIndex = index;
                        break;
                    }*/
					if (listBetweenDates.contains(tradeTime)) {	                     
	                     tradeTimeList.put(tradeTime,index); 
	                }
                    if("合计".equals(tradeTimeOld) || index > 100){
                        break;
                    }
                    index ++;
                }

                for (int m = 1; m < listMap.size(); m++) {

                    Map<Integer, String> data = listMap.get(m);
                    // 返回每条数据的键值对 表示所在的列 和所在列的值
                    LOGGER.info("读取到数据:{}", JSON.toJSONString(data));
                    if(data.get(0) == null || !Character.isDigit(data.get(0).toCharArray()[0])){
                        continue;
                    }
                    for (Map.Entry<String, Integer> entry : tradeTimeList.entrySet()) {
					    SwCkBankCashPaymentNoteTmp tmpObj = new SwCkBankCashPaymentNoteTmp();
						tmpObj.setLineCodeTmp(lineName);
						tmpObj.setStationCodeTmp(data.get(1));//车站
						tmpObj.setTradeTimeTmp(entry.getKey());
						tmpObj.setAmountTmp(data.get(entry.getValue()));

						if (StringUtils.isEmpty(tmpObj.getTradeTimeTmp())
								|| StringUtils.isEmpty(tmpObj.getAmountTmp())
								|| StringUtils.isEmpty(tmpObj.getLineCodeTmp())
								|| StringUtils.isEmpty(tmpObj.getStationCodeTmp())
								) {
							continue;
						}
						if (!parseDate(tmpObj.getTradeTimeTmp())) {
							continue;
						}

						final SwCkBankCashPaymentNoteTmp obj = ObjectUtils.getDefaultObj(SwCkBankCashPaymentNoteTmp.class);
						BeanUtils.copyProperties(tmpObj, obj,  "creatorId", "creatorName");
						checkErr(obj,lineMap,stationMap);
						listDb.add(obj);
					}
                   
                }
            }
        }


        MultipartFileToFile.delteTempFile(excelFile);
        if(!listDb.isEmpty()) {
            Map<String, Object> columnMap = new HashMap<>();
            columnMap.put("CREATOR_ID", listDb.get(0).getCreatorId());
            this.baseMapper.deleteByMap(columnMap);
            return  this.saveBatch(listDb);
        }

        return false;

    }

    /**
     * 格式化Excel时间
     * @param day
     * @return yyyy-MM-dd
     */
    private String formatExcelDate(int day) {
        Calendar calendar = new GregorianCalendar(1900,0,-1);
        calendar.add(Calendar.DATE, day);
        Date gregorianDate = calendar.getTime();
        String formatExcelDate = DateUtils.format(gregorianDate, parsePattern);
        return formatExcelDate;
    }

    private String getLineCode (List<Map<String,String>> lineMap,String lineName) {
        for (Map<String,String> map : lineMap){
            if(lineName.equals(map.get("NAME"))){
                return map.get("CODE");
            }
        }
        return "";
    }

    private String getStationCode (List<Map<String,String>> stationMap,String stationName,String lineCode) {
        for (Map<String,String> map : stationMap){
            if(stationName.equals(map.get("NAME")) && lineCode.equals(map.get("LINE_CODE"))){
                return map.get("CODE");
            }
        }
        return "";
    }

    private void checkErr(SwCkBankCashPaymentNoteTmp obj, List<Map<String,String>> lineMap, List<Map<String,String>> stationMap) {
        //更新字段
        String tradeTimeTmp = obj.getTradeTimeTmp();
        try {
            Date tradeTime = DateUtils.parseDate(tradeTimeTmp, parsePattern);
            obj.setTradeTime(tradeTime.toInstant().atZone(ZoneId.systemDefault()).toLocalDate());
        } catch (Exception e) {
            obj.setErrMsg("交易日期 为空或格式错误");
        }

        if(StringUtils.isNotEmpty(obj.getLineCodeTmp())){
            String lineCode = getLineCode(lineMap,obj.getLineCodeTmp());
            if(StringUtils.isNotEmpty(lineCode)){
                obj.setLineCode(lineCode);
            } else {
                obj.setErrMsg("线路名称 为空或不规范");
            }

        } else {
            obj.setErrMsg("线路名称 为空");
        }

        if(StringUtils.isNotEmpty(obj.getStationCodeTmp()) && StringUtils.isNotEmpty(obj.getLineCode())){
            String stationCode = getStationCode(stationMap,obj.getStationCodeTmp(),obj.getLineCode());
            if(StringUtils.isNotEmpty(stationCode)){
                obj.setStationCode(stationCode);
            } else {
                obj.setErrMsg("车站名称 为空或不规范");
            }
        } else {
            obj.setErrMsg("车站名称 为空");
        }
        try {
            BigDecimal num = new BigDecimal("100");

            String amountTmp = obj.getAmountTmp();
            BigDecimal money = new BigDecimal(amountTmp).setScale(2, BigDecimal.ROUND_HALF_UP);
            money = money.multiply(num);
            obj.setAmount(money);

        } catch (Exception e) {
            obj.setErrMsg("金额 为空或格式错误");
        }

        obj.setDataSource("2");
        obj.setCreateTime(LocalDateTime.now());

        //int countLongPeriodSettlement = this.baseMapper.countLongPeriodSettlement(obj.getLineCode(),obj.getStationCode());  20241106	
		String myTradeTime = MyDateUtil.LocalDateTurnString(obj.getTradeTime());      
        int countLongPeriodSettlement = this.baseMapper.getIsLongTime(obj.getLineCode(),obj.getStationCode(),myTradeTime);
        String dataType = null;
		
        if (countLongPeriodSettlement > 0){
            dataType = SW_CK_BANK_CASH_PAYMENT_NOTE_DATA_TYPE.LONG_CYCLE.getCode();			
        } else {
            dataType = SW_CK_BANK_CASH_PAYMENT_NOTE_DATA_TYPE.BANK_BILL.getCode();			
        }
        obj.setDataType(dataType);
        SwCkBankCashPaymentNote note = swCkBankCashPaymentNoteService.getUnloadShortAmount(dataType, obj.getLineCode(), obj.getStationCode(),obj.getTradeTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
        obj.setEntryStartTime(note.getEntryStartTime());
        obj.setEntryEndTime(note.getEntryEndTime());
        obj.setSupShortAmount(note.getSupShortAmount());
        obj.setSupUnloadAmount(note.getSupUnloadAmount());

        //判断数据是否存在
        SwCkBankCashPaymentNote swCkBankCashPaymentNote = new SwCkBankCashPaymentNote();
        swCkBankCashPaymentNote.setLineCode(obj.getLineCode());
        swCkBankCashPaymentNote.setStationCode(obj.getStationCode());
        swCkBankCashPaymentNote.setTradeTime(obj.getTradeTime());
        swCkBankCashPaymentNote.setDelFlag("0");
        int count= swCkBankCashPaymentNoteService.count(Wrappers.query(swCkBankCashPaymentNote));
        if (count > 0 && StringUtils.isEmpty(obj.getErrMsg())) {
            obj.setErrMsg("数据已存在");
        }
    }

    private boolean parseDate(String string) {
        boolean convertSuccess = true;
        if (string == null) {
            return false;
        }

        try {
            DateUtils.parseDate(string, parsePattern);
        } catch (ParseException e) {
            convertSuccess = false;
        }
        return convertSuccess;
    }

    @Override
    public void saveBatchWithExcelOk(Integer creatorId) {
		/*
		  是否适用此方法待定---对于数据已经存在，业务规则改为覆盖原有数据		 
		*/
		 this.baseMapper.deleteBatchWithExcelOk(creatorId);//先删除原来的数据
         this.baseMapper.saveBatchWithExcelOkRepeat(creatorId);
        //this.baseMapper.saveBatchWithExcelOk(creatorId);
        saveBatchWithExcelCancel(creatorId);
    }
    @Override
    public void saveBatchWithExcelCancel(Integer creatorId) {
        Map<String, Object> columnMap = new HashMap<>();
        columnMap.put("CREATOR_ID", creatorId);
        this.baseMapper.deleteByMap(columnMap);
    }

    @Override
    public void exportTamplates(HttpServletResponse response) {
        String  verifyConfirmName = "银行现金缴款单";
        String  tableName = "sw_ck_bank_cash_payment_note";

        BufferedInputStream br = null;
        OutputStream out = null;
        try {
            response.reset(); // 非常重要
            response.setContentType("application/vnd.ms-excel");
            response.setCharacterEncoding("utf-8");
            final String fileName = URLEncoder.encode(verifyConfirmName, "UTF-8");
            response.setHeader("Content-disposition", "attachment;filename=" + fileName + System.currentTimeMillis() + ".xls");

            br =  new BufferedInputStream(this.getClass().getResourceAsStream("/static/excel/template/import/" + tableName + ".xls"));

            byte[] buf = new byte[1024];
            int len = 0;

            out = response.getOutputStream();
            while ((len = br.read(buf)) > 0) {
                out.write(buf, 0, len);
            }

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if(out != null) {
                try {
                    out.close();
                } catch (IOException ioe) {
                    ioe.printStackTrace();
                }
            }
            if(br != null){
                try {
                    br.close();
                } catch (IOException ioe) {
                    ioe.printStackTrace();
                }
            }
        }
    }


}
